package com.xyw.code.gateway.admin.service.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.CreateCache;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyw.code.bus.common.entity.form.SendMessageForm;
import com.xyw.code.bus.common.feign.SendMessageRemoteApi;
import com.xyw.code.common.core.constant.IsDelEnum;
import com.xyw.code.gateway.admin.config.BusConfig;
import com.xyw.code.gateway.admin.dao.GatewayRouteMapper;
import com.xyw.code.gateway.admin.service.IGatewayRouteService;
import com.xyw.code.gateway.common.entity.enums.RouteDefinitionMessageTagEnum;
import com.xyw.code.gateway.common.entity.po.GatewayRoute;
import com.xyw.code.gateway.common.entity.vo.RouteDefinitionMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.net.URI;
import java.util.List;

/**
 * <p>
 * 网关路由表 服务实现类
 * </p>
 *
 * @author xyw
 * @since 2020-01-31
 */
@Service
@Slf4j
public class GatewayRouteServiceImpl  extends ServiceImpl<GatewayRouteMapper, GatewayRoute> implements IGatewayRouteService {

    private static final String GATEWAY_ROUTES = "gateway_routes::";

    @CreateCache(name =  GATEWAY_ROUTES, cacheType = CacheType.REMOTE)
    private Cache<String, RouteDefinition> gatewayRouteCache;

    @Autowired
    private SendMessageRemoteApi sendMessageRemoteApi;

    @Override
    @PostConstruct
    public boolean overload() {
        List<GatewayRoute> gatewayRoutes = baseMapper.selectList(Wrappers.<GatewayRoute>lambdaQuery().eq(
                GatewayRoute::getDelFlag, IsDelEnum.USE.getKey()
        ));
        //得到然后遍历放置进map
        gatewayRoutes.forEach(gatewayRoute -> {
            gatewayRouteCache.put(gatewayRoute.getRouteId(),gatewayRouteToRouteDefinition(gatewayRoute));
        });
        log.info("全局初始化网关路由转换成功");
        return true;
    }

    @Override
    public boolean add(GatewayRoute gatewayRoute) {
        boolean isSuccess = this.save(gatewayRoute);
        RouteDefinition routeDefinition = gatewayRouteToRouteDefinition(gatewayRoute);
        gatewayRouteCache.put(routeDefinition.getId(),routeDefinition);
        RouteDefinitionMessage routeDefinitionMessage = new RouteDefinitionMessage(RouteDefinitionMessageTagEnum.ADD.getKey(),routeDefinition);
        SendMessageForm sendMessageForm = new SendMessageForm(JSONObject.toJSONString(routeDefinitionMessage),BusConfig.EXCHANGE_NAME,BusConfig.ROUTING_KEY,null,null);
        sendMessageRemoteApi.sendMessage(sendMessageForm);
        return isSuccess;
    }

    @Override
    public boolean update(GatewayRoute gatewayRoute) {
        boolean isSuccess = this.updateById(gatewayRoute);
        RouteDefinition routeDefinition = gatewayRouteToRouteDefinition(gatewayRoute);
        gatewayRouteCache.put(routeDefinition.getId(),routeDefinition);
        RouteDefinitionMessage routeDefinitionMessage = new RouteDefinitionMessage(RouteDefinitionMessageTagEnum.UPDATE.getKey(),routeDefinition);
        SendMessageForm sendMessageForm = new SendMessageForm(JSONObject.toJSONString(routeDefinitionMessage),BusConfig.EXCHANGE_NAME,BusConfig.ROUTING_KEY,null,null);
        sendMessageRemoteApi.sendMessage(sendMessageForm);
        return isSuccess;
    }

    @Override
    public boolean delete(String id) {
        GatewayRoute gatewayRoute = this.getById(id);
        // 删除redis缓存, 并事件通知各网关应用
        gatewayRouteCache.remove(gatewayRoute.getRouteId());
        RouteDefinition routeDefinition = gatewayRouteToRouteDefinition(gatewayRoute);
        RouteDefinitionMessage routeDefinitionMessage = new RouteDefinitionMessage(RouteDefinitionMessageTagEnum.DEL.getKey(),routeDefinition);
        SendMessageForm sendMessageForm = new SendMessageForm(JSONObject.toJSONString(routeDefinitionMessage),BusConfig.EXCHANGE_NAME,BusConfig.ROUTING_KEY,null,null);
        sendMessageRemoteApi.sendMessage(sendMessageForm);
        return this.removeById(id);
    }

    @Override
    public GatewayRoute get(String id) {
        return this.getById(id);
    }

    /**
     * 将数据库存储的对象换成网关需要的对象
     * @param gatewayRoute
     * @return
     */
    private RouteDefinition gatewayRouteToRouteDefinition(GatewayRoute gatewayRoute) {
        RouteDefinition routeDefinition = new RouteDefinition();
        routeDefinition.setId(gatewayRoute.getRouteId());
        routeDefinition.setOrder(gatewayRoute.getOrders());
        routeDefinition.setUri(URI.create(gatewayRoute.getUri()));
        routeDefinition.setFilters(JSONArray.parseArray(gatewayRoute.getFilters(), FilterDefinition.class));
        routeDefinition.setPredicates(JSONArray.parseArray(gatewayRoute.getPredicates(), PredicateDefinition.class));
        return routeDefinition;
    }
}
